


from tool_match import *
from bf_lex import *
from bf_parseline import *


table = {
    "$line_else": Pat("Lelse", Word('else')),
    "$line_noelse": Pat("Lnoelse", Word('noelse')),

    "$word": Pat("Oword", Word),
    "$num": Pat("Onum", Num),
    "$string": Pat("Ostring", String),
    "$rawlist": Pat("Orawlist", RawList),
    "$rawtuple": Pat("Orawtuple", RawTuple),

    "$literal": Pat("Oliteral", ["$word", "$num", "$string", "$rawlist", "$rawtuple"]),
    "$exp1": Pat('Oexp1', (['+', '-']-cu-"1f", '$exp'-cu-"1x")),
    "$exp2": Pat('Oexp2', (['+', '-', '*', '**', '/', '%', '<', '>', '>=', '<=', '==', '!=', 'in', '.', 'item', 'call']-cu-"2f", '$exp'-cu-"2x", '$exp'-cu-"2y")),
    "$exp" : Pat('Oexp', ["$literal", "$exp1", "$exp2", ]),
    "$item": Pat("Oitem", ("item", "$exp"-cu-"ix", object-cu-"iy")),
    "$attr": Pat("Oattr", (".", "$exp"-cu-"ax", "$word"-cu-"ay")),

    "$line_assign" : Pat('Lassign', ("=", ["$rawtuple", "$word", "$item", "$attr"]-cl-"x", ["$exp"-cu-"y", "$line_assign"])),


    "$line_if" : Pat('Lif', ("if", "$exp"-cu-"x")),
    "$line_elif" : Pat('Lelif', ("elif", "$exp"-cu-"x")),
    "$line_for" : Pat('Lfor', ('in', ('for', "$exp"-cu-'x'), "$exp"-cu-'l')),

    "$_other": Pat('???', object),
    "code": Pat("code", ["$line_else", "$line_noelse", "$exp", "$line_assign" ,  "$line_if", "$line_elif",  "$line_for", "$_other"]-cu-"code")
}

link(table)

'''

def list_scan(x):       # 对于match后的数据，把嵌套的list元素也解析
    if type(x) == list: # block
        return [list_scan(m) for m in x]

    print("scanning", x)
    if type(x[1]) is dict:
        for y in x[1]:
            x[1][y] = list_scan(x[1][y])
        return x
    elif x[0] == Pat("Oword", 1) or x[0] == Pat("Onum", 1) or x[0] == Pat("Ostring", 1):
        return x
    elif x[0] == Pat("Orawlist", 1):
        x[1].l = [list_scan(trans(y)) for y in x[1].l]
        return x
    elif x[0] == Pat("Orawtuple", 1):
        print("here")
        x[1].l = [list_scan(trans(y)) for y in x[1].l]
        # ~ x[1].l = [list_scan(y) for y in x[1].l]
        return x
    else:
        return x
'''

def parseline_step2(tree):
    b, d = match_collect(tree, table["code"])
    if b:
        return d["code"]
        #return list_scan(d["code"])
    else:
        raise Exception("无法转换")


def showparse2(rr):
    from tool_treeprint import tree
    from dataclasses import dataclass
    @dataclass
    class Pair:
        a: object
        b: object

    def name(o):
        if isinstance(o ,dict):
            return ""
        elif isinstance(o, list):
            return "~"
        elif isinstance(o, tuple):
            return name(o[0]) + name(o[1])
        elif isinstance(o, Pair):
            return name(o.a) + ': ' + name(o.b)
        else:
            return str(o)

    def member(o):
        if isinstance(o ,dict):
            return [Pair(k, v) for k, v in o.items()]
        elif isinstance(o, list):
            return list(o)
        elif isinstance(o, tuple):
            return member(o[1])
        elif isinstance(o, Pair):
            return member(o.b)
        else:
            return []

    tree(rr, name, member)

def parseline(linel):
    r = parseline_step1(linel)
    
    rr = parseline_step2(r)
    
    return rr

def test(s):
    doc = scan(s)
    line  = doc.l[0]
    print(line)
    r = parseline_step1(line.l)
    print(r)
    showparse1(r)
    rr = parseline_step2(r)
    print(rr)
    showparse2(rr)



if __name__ == "__main__":
    #test("abs(a + b) * 2")
    test('print(1+ 2)')
    #test("l[0][1][2] = l[2]")
    # ~ test("a = 1 + 2 * 3")
    # ~ test("1 * 2 + 3 = b")
    #test("l[0][1][2] = l[2]")
    # ~ test("a = 1 + 2 * 3")
 #   test("p.x[0] ** 2 + p[1].x ** 2  + static()[]")
    # ~ test("l[i] = m.p = p = (x, y) = (4, 5)")
    # ~ test("p.x[0] ** 2 + p[1].x ** 2  + static().[]()")

    """
<Lassign>
┣ ━ x: ~
┃   ┣ ━ <Oitem>
┃   ┃   ┣ ━ ix: <Oword>l
┃   ┃   ┗ ━ iy: p@<class 'object'>[[i]]
┃   ┣ ━ <Oattr>
┃   ┃   ┣ ━ ax: <Oword>m
┃   ┃   ┗ ━ ay: <Oword>p
┃   ┣ ━ <Oword>p
┃   ┗ ━ <Orawtuple>([x], [y])
┗ ━ y: <Orawtuple>([4], [5])

<Oexp3>
┣ ━ 2x: <Oexp3>
┃   ┣ ━ 2x: <Oexp3>
┃   ┃   ┣ ━ 2x: <Oexp3>
┃   ┃   ┃   ┣ ━ 2x: <Oexp3>
┃   ┃   ┃   ┃   ┣ ━ 2x: <Oword>p
┃   ┃   ┃   ┃   ┗ ━ 2y: <Oword>x
┃   ┃   ┃   ┗ ━ 2y: <Orawlist>[[0]]
┃   ┃   ┗ ━ 2y: <Onum>2
┃   ┗ ━ 2y: <Oexp3>
┃       ┣ ━ 2x: <Oexp3>
┃       ┃   ┣ ━ 2x: <Oexp3>
┃       ┃   ┃   ┣ ━ 2x: <Oword>p
┃       ┃   ┃   ┗ ━ 2y: <Orawlist>[[1]]
┃       ┃   ┗ ━ 2y: <Oword>x
┃       ┗ ━ 2y: <Onum>2
┗ ━ 2y: <Oexp3>
    ┣ ━ 2x: <Oexp3>
    ┃   ┣ ━ 2x: <Oword>static
    ┃   ┗ ━ 2y: <Orawtuple>()
    ┗ ━ 2y: <Orawlist>[]

    """

    #test('elif 1 == a')
